'use strict';

const db = uniCloud.database()
const $ = db.command.aggregate
const _ = db.command

// 添加 QPS 控制相关变量
let lastRequestTime = 0
const MIN_INTERVAL = 500 // 最小请求间隔为 500ms，确保 QPS <= 2

exports.main = async (event, context) => {
	// 判断是否为定时触发
	if (event.Type === 'Timer') {
		console.log('定时触发执行, 触发时间:', event.Time)
		return await scheduledUpdate()
	}
	
	const { action, params = {} } = event

	switch (action) {
		case 'getNewsList':
			return await getNewsList(params)

		case 'getNewsDetail':
			return await getNewsDetail(params)

		case 'scheduledUpdate':
			return await scheduledUpdate()

		case 'batchAnalyzeNews':
			return await batchAnalyzeNews(params)

		default:
			return {
				code: 404,
				msg: '未找到对应的操作'
			}
	}
}

async function generateAIDescription(prompt) {
	try {
		// 配置信息
		const url = 'https://spark-api-open.xf-yun.com/v1/chat/completions'
		const apiPassword = 'KTmyqFZZVglaDJEmKrvN:RCxEaQXdTtxlwopyUqSC'

		// 构建请求数据
		const data = {
			model: '4.0Ultra',
			messages: [
				{
					role: 'system',
					content: prompt
				},
				{
					role: 'user',
					content: "请你直接输出完整新闻分析JSON数据"
				}
			],
			temperature: 0.3,  // 降低温度，使输出更稳定
			max_tokens: 4096
		}

		// 构建请求头
		const headers = {
			'Authorization': `Bearer ${apiPassword}`,
			'Content-Type': 'application/json'
		}

		// 发送请求
		console.log('发送请求:', {
			url,
			headers,
			data
		})

		const response = await uniCloud.httpclient.request(url, {
			method: 'POST',
			data: data,
			headers: headers,
			dataType: 'json',
			timeout: 30000
		})

		console.log('响应状态码:', response.status)
		console.log('响应数据:', response.data)

		if (response.status === 200 && response.data.code === 0) {
			const result = response.data
			if (result.choices && result.choices.length > 0) {
				return result.choices[0].message.content
			}
		}

		throw new Error('调用大模型失败: ' + JSON.stringify(response.data))

	} catch (e) {
		console.error('调用大模型异常:', e)
		return '分析失败,请稍后重试'
	}
}


// 获取新闻列表
async function getNewsList({ page = 1, pageSize = 10 } = {}) {
	try {
		console.log('[获取新闻列表] 开始执行...')
		console.log(`[获取新闻列表] 参数: page=${page}, pageSize=${pageSize}`)

		const skip = (page - 1) * pageSize
		console.log(`[获取新闻列表] 计算跳过条数: skip=${skip}`)

		// 直接从数据库获取新闻
		console.log('[获取新闻列表] 正在查询数据库...')
		const result = await db.collection('a_news')
			.orderBy('time', 'desc')
			.skip(skip)
			.limit(pageSize)
			.get()
		console.log(`[获取新闻列表] 查询成功,获取到 ${result.data.length} 条记录`)

		// 格式化响应
		console.log('[获取新闻列表] 正在格式化响应数据...')
		console.log('[获取新闻列表] 格式化数据:', result.data)
		const response = formatNewsListResponse(result.data)
		console.log('[获取新闻列表] 格式化完成,准备返回数据')
		return response

	} catch (e) {
		console.error('[获取新闻列表] 发生错误:', e)
		return { code: 500, msg: e.message }
	}
}

// 修改格式化新闻列表响应函数
function formatNewsListResponse(newsList) {
	// 提取所有新闻的分类
	const sectors = [...new Set(newsList.map(item => item.category))]
		.filter(Boolean) // 过滤掉空值
		.map(category => ({
			id: category,
			name: category,
			count: newsList.filter(item => item.category === category).length
		}))

	// 格式化新闻列表
	const formattedList = newsList.map((item, index) => ({
		id: item._id,  // 使用数据库的_id
		title: item.title,
		source: item.src,
		time: item.time,
		sector: item.category,
		relatedConcepts: item.analysis && item.analysis.relatedSectors || [], // 如果有分析结果，使用keyPoints作为相关概念
		summary: item.analysis && item.analysis.summary || '', // 添加摘要
		marketImpact: item.analysis && item.analysis.marketImpact || '' // 添加市场影响
	}))

	return {
		code: 200,
		msg: 'ok',
		data: {
			sectors,
			list: formattedList
		}
	}
}

// 获取新闻详情
async function getNewsDetail({ id }) {
	try {
		if (!id) {
			return {
				code: 400,
				msg: '缺少新闻ID'
			}
		}

		// 从数据库获取新闻
		const news = await db.collection('a_news')
			.doc(id)
			.get()

		if (!news.data || news.data.length === 0) {
			return {
				code: 404,
				msg: '新闻不存在'
			}
		}

		const newsData = news.data[0]
		return {
			code: 200,
			msg: 'ok',
			data: {
				// 基本信息
				title: newsData.title,
				source: newsData.source,
				time: newsData.time,
				content: newsData.content,

				// AI分析
				analysis: newsData.analysis || {
					summary: '暂无AI分析',
					keyPoints: ['暂无要点分析'],
					marketImpact: '暂无市场影响分析'
				},

				// 相关板块
				relatedSectors: newsData.analysis && newsData.analysis.relatedSectors ? 
					newsData.analysis.relatedSectors.map(sector => ({
						name: sector,
						trend: 0
					})) : [{
						name: newsData.category,
						trend: 0
					}],

				// 相关个股
				relatedStocks: newsData.analysis && newsData.analysis.relatedStocks ? 
					newsData.analysis.relatedStocks.map(stock => ({
						code: stock.code || '',
						name: stock.name || '',
						change: 0,
						reason: stock.reason || ''
					})) : []
			}
		}

	} catch (e) {
		console.error('获取新闻详情异常:', e)
		return {
			code: 500,
			msg: '获取新闻详情失败:' + e.message
		}
	}
}

// 添加从API获取新闻的函数
async function fetchNewsFromAPI(type='股票') {
	try {
		console.log('[获取新闻] 开始从API获取新闻...')
		
		// API配置
		const apiConfig = {
			baseUrl: 'https://api.tanshuapi.com/api/toutiao/v1/index',
			params: {
				key: 'a798a05ba280db5a987b751dea7c3459',
				type: type,
				num: 40,
				start: 0
			}
		}
		
		console.log('[获取新闻] 准备发送请求:', {
			url: apiConfig.baseUrl,
			type: apiConfig.params.type,
			num: apiConfig.params.num
		})

		// 发送请求
		const response = await uniCloud.httpclient.request(apiConfig.baseUrl, {
			method: 'GET',
			data: apiConfig.params,
			dataType: 'json',
			timeout: 10000, // 10秒超时
			headers: {
				'User-Agent': 'Mozilla/5.0 (compatible; NewsBot/1.0;)'
			}
		})

		// 详细的响应日志
		console.log('[获取新闻] API响应状态:', response.status)
		console.log('[获取新闻] API响应码:', response.data && response.data.code)
		console.log('[获取新闻] API响应数据:', response.data)

		// 验证响应
		if (!response.data) {
			throw new Error('API返回数据为空')
		}

		if (response.status !== 200) {
			throw new Error(`API请求失败，HTTP状态码: ${response.status}`)
		}

		if (response.data.code !== 1) {
			throw new Error(`API业务处理失败，错误码: ${response.data.code}, 消息: ${response.data.msg || '未知错误'}`)
		}

		// 验证并转换数据结构
		const newsList = response.data.data.list || []
		if (!Array.isArray(newsList)) {
			throw new Error('API数据格式错误：新闻列表不是数组格式')
		}

		// 验证每条新闻数据的必要字段
		const validatedNewsList = newsList.map(news => {
			if (!news.title || !news.time || !news.content) {
				console.log('[数据验证] 发现无效新闻数据:', news)
				return null
			}
			return {
				title: news.title,
				time: news.time,
				source: news.src || '',
				category: news.category || '',
				image: news.pic || '',
				url: news.weburl || news.url || '',
				content: news.content
			}
		}).filter(Boolean) // 过滤掉无效的新闻

		if (validatedNewsList.length === 0) {
			throw new Error('API返回数据无有效新闻')
		}

		return validatedNewsList

	} catch (e) {
		console.error('[获取新闻] API请求失败:', e)
		throw new Error('新闻API请求失败: ' + e.message)
	}
}

// 修改保存新闻到数据库的函数
async function saveNewsToDatabase(newsList) {
	try {
		console.log(`[保存新闻] 开始处理 ${newsList.length} 条新闻`)

		// 构建批量插入的数据
		const batch = newsList.map(news => ({
			title: news.title,
			source: news.src,
			time: news.time,
			content: news.content,
			category: news.category,
			url: news.url,
			create_time: new Date(),
			update_time: new Date(),
			is_analyzed: false,
			api_id: news.id
		}))

		// 批量插入数据库
		console.log('[保存新闻] 正在批量插入数据库...')
		await db.collection('a_news').add(batch)
		console.log('[保存新闻] 数据库插入完成')

		// 触发AI分析
		console.log('[保存新闻] 开始进行AI分析...')
		let successCount = 0
		let failCount = 0

		for (const news of batch) {
			try {
				console.log(`[保存新闻] 正在分析: ${news.title}`)
				await analyzeNews(news)
				successCount++
			} catch (err) {
				failCount++
				console.error(`[保存新闻] 分析失败: ${news.title}`, err)
				
				// 设置默认分析结果
				try {
					await db.collection('a_news')
						.where({ api_id: news.api_id })
						.update({
							analysis: {
								summary: '暂无分析',
								keyPoints: ['等待分析'],
								marketImpact: '暂无影响分析',
								relatedSectors: []
							},
							is_analyzed: true,
							update_time: new Date()
						})
					console.log(`[保存新闻] 已设置默认分析结果: ${news.title}`)
				} catch (updateErr) {
					console.error('[保存新闻] 设置默认分析结果失败:', updateErr)
				}
			}
		}

		console.log('[保存新闻] 处理完成:', {
			total: batch.length,
			success: successCount,
			fail: failCount
		})

		return {
			success: true,
			total: batch.length,
			analyzed: successCount,
			failed: failCount
		}

	} catch (e) {
		console.error('[保存新闻] 发生错误:', e)
		return {
			success: false,
			error: e.message
		}
	}
}

// 添加AI分析函数
async function analyzeNews(news) {
	try {
		console.log(`[AI分析] 开始分析新闻: ${news.title}`)

		// 1. 生成分析提示
		console.log('[AI分析] 正在生成分析提示...')
		const prompt = `
你是一个专业的金融分析师，请分析以下新闻：

${news.title}
${news.content}

请提供：
1. 核心总结（100字以内）
2. 3-5个关键要点
3. 市场影响分析（100字以内）
4. 相关板块
5. 可能受影响的股票类型

请用JSON格式返回，格式如下：
{
  "summary": "核心总结",
  "keyPoints": ["要点1", "要点2", "要点3"],
  "marketImpact": "市场影响分析",
  "relatedSectors": ["板块1", "板块2"],
  "relatedStocks": ["股票类型1", "股票类型2"]
}
`
		// 2. 调用AI生成分析
		console.log('[AI分析] 正在调用AI服务...')
		const analysisText = await generateAIDescription(prompt)
		
		// 3. 解析JSON结果
		console.log('[AI分析] AI响应成功，正在解析JSON...')
		let analysis
		try {
			// 提取JSON字符串（处理可能的前后缀文本）
			const jsonMatch = analysisText.match(/\{[\s\S]*\}/)
			if (jsonMatch) {
				// 去除可能存在的代码块标记
				const cleanJson = jsonMatch[0].replace(/```json|```/g, '').trim()
				analysis = JSON.parse(cleanJson)
			} else {
				throw new Error('未找到有效的JSON数据')
			}
		} catch (parseError) {
			console.error('[AI分析] JSON解析失败:', parseError)
			// 使用默认值
			analysis = {
				summary: '无法解析AI返回的分析结果',
				keyPoints: ['解析失败'],
				marketImpact: '解析失败',
				relatedSectors: [],
				relatedStocks: []
			}
		}

		// 4. 更新数据库
		console.log('[AI分析] 正在更新数据库...')
		await db.collection('a_news')
			.where({
				api_id: news.api_id
			})
			.update({
				analysis: {
					summary: analysis.summary,
					keyPoints: analysis.keyPoints,
					marketImpact: analysis.marketImpact,
					relatedSectors: analysis.relatedSectors || []
				},
				is_analyzed: true,
				update_time: new Date()
			})
		console.log('[AI分析] 数据库更新成功')

	} catch (e) {
		console.error('[AI分析] 发生错误:', {
			newsTitle: news.title,
			error: e.message,
			stack: e.stack
		})
		throw e // 向上抛出错误，便于调用方处理
	}
}

// 修改定时更新函数
async function scheduledUpdate() {
	try {
		console.log('[定时更新] 开始执行...')

		// 1. 获取最新的新闻
		console.log('[定时更新] 正在从API获取最新新闻...')
		const apiResponse = await fetchNewsFromAPI()
		console.log('[定时更新] API返回原始数据:', apiResponse)

		// 2. 直接使用 apiResponse 中的新闻列表
		const newsList = apiResponse // apiResponse 已经是新闻列表数组了
		console.log(`[定时更新] 获取到 ${newsList.length} 条新闻`)

		// 3. 获取数据库中已存在的新闻标题
		console.log('[定时更新] 正在查询数据库中已存在的新闻...')
		const existingNews = await db.collection('a_news')
			.where({
				title: db.command.in(newsList.map(news => news.title))
			})
			.field({
				title: 1
			})
			.get()

		const existingTitles = new Set(existingNews.data.map(news => news.title))
		console.log(`[定时更新] 数据库中已有 ${existingTitles.size} 条重复新闻`)

		// 4. 过滤出新的新闻
		const newNewsItems = newsList.filter(news => !existingTitles.has(news.title))
		console.log(`[定时更新] 过滤得到 ${newNewsItems.length} 条新新闻`)

		if (newNewsItems.length === 0) {
			console.log('[定时更新] 没有新的新闻需要更新，任务结束')
			return {
				code: 200,
				msg: 'ok',
				data: { updated: 0 }
			}
		}

		// 5. 保存新新闻到数据库
		console.log('[定时更新] 开始保存新新闻到数据库...')
		await saveNewsToDatabase(newNewsItems)

		console.log(`[定时更新] 任务完成，成功新增 ${newNewsItems.length} 条新闻`)
		return {
			code: 200,
			msg: 'ok',
			data: { updated: newNewsItems.length }
		}

	} catch (e) {
		console.error('[定时更新] 发生错误:', e)
		return {
			code: 500,
			msg: '更新失败:' + e.message
		}
	}
}

// 批量分析新闻
async function batchAnalyzeNews({ batchSize = 100 } = {}) {
	try {
		console.log('[批量分析] 开始执行...')

		// 1. 获取待分析的新闻
		const pendingNews = await db.collection('a_news')
			.where({
				is_analyzed: false
			})
			.limit(batchSize)
			.get()

		if (!pendingNews.data.length) {
			return {
				code: 200,
				msg: 'ok',
				data: {
					analyzed: 0,
					message: '没有待分析的新闻'
				}
			}
		}

		console.log(`[批量分析] 找到 ${pendingNews.data.length} 条待分析新闻`)

		// 2. 循环分析新闻
		let successCount = 0
		let failCount = 0

		for (const news of pendingNews.data) {
			try {
				console.log(`[批量分析] 正在分析新闻: ${news.title}`)

				// 控制请求频率
				const now = Date.now()
				const timeSinceLastRequest = now - lastRequestTime
				if (timeSinceLastRequest < MIN_INTERVAL) {
					const waitTime = MIN_INTERVAL - timeSinceLastRequest
					console.log(`[QPS控制] 等待 ${waitTime}ms`)
					await new Promise(resolve => setTimeout(resolve, waitTime))
				}
				lastRequestTime = Date.now()

				// 2.1 生成分析提示
				const prompt = `
你是一个专业的金融分析师，请分析以下新闻：

${news.title}
${news.content}

请严格按照以下JSON格式返回分析结果（注意：必须返回合法的JSON格式）：
{
  "summary": "这里是核心总结（100字以内）",
  "keyPoints": ["这里是要点1", "这里是要点2", "这里是要点3"],
  "marketImpact": "这里是市场影响分析（100字以内）",
  "relatedSectors": ["这里是相关板块1", "这里是相关板块2"]
}
`

				// 2.2 调用AI分析
				const analysisText = await generateAIDescription(prompt)
				
				// 2.3 尝试解析JSON
				let analysis
				try {
					// 提取JSON字符串（处理可能的前后缀文本）
					const jsonMatch = analysisText.match(/\{[\s\S]*\}/)
					if (jsonMatch) {
						// 去除可能存在的代码块标记
						const cleanJson = jsonMatch[0].replace(/```json|```/g, '').trim()
						analysis = JSON.parse(cleanJson)
					} else {
						throw new Error('未找到有效的JSON数据')
					}
				} catch (parseError) {
					console.error('[批量分析] JSON解析失败:', parseError)
					// 使用默认值
					analysis = {
						summary: '无法解析AI返回的分析结果',
						keyPoints: ['解析失败'],
						marketImpact: '解析失败',
						relatedSectors: []
					}
				}

				// 2.4 更新数据库
				await db.collection('a_news')
					.doc(news._id)
					.update({
						analysis: {
							summary: analysis.summary,
							keyPoints: analysis.keyPoints,
							marketImpact: analysis.marketImpact,
							relatedSectors: analysis.relatedSectors || []
						},
						is_analyzed: true,
						update_time: new Date()
					})

				successCount++
				console.log(`[批量分析] 新闻分析成功: ${news.title}`)

			} catch (e) {
				failCount++
				console.error(`[批量分析] 新闻分析失败: ${news.title}`, e)
			}
		}

		return {
			code: 200,
			msg: 'ok',
			data: {
				total: pendingNews.data.length,
				success: successCount,
				fail: failCount
			}
		}

	} catch (e) {
		console.error('[批量分析] 执行异常:', e)
		return {
			code: 500,
			msg: '批量分析失败:' + e.message
		}
	}
} 